package service

import (
	"encoding/json"
	"errors"
	"github.com/gogf/gf/container/garray"
	"github.com/gogf/gf/crypto/gmd5"
	"github.com/gogf/gf/database/gdb"
	"github.com/gogf/gf/encoding/gjson"
	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/net/ghttp"
	"github.com/gogf/gf/os/gtime"
	"github.com/gogf/gf/text/gstr"
	"github.com/gogf/gf/util/gconv"
	"time"
	"web_api_gogf/app/dao"
	"web_api_gogf/app/model"
)

// SysUser 系统用户逻辑类
var SysUser = SysUserService{}

type SysUserService struct {
}

// 获取密码字符串
func (s *SysUserService) GetUserPassword(password string) (string, error) {
	passwordStr := "gogf_web_admin:" + password
	encryptPwd, err := gmd5.EncryptString(passwordStr)
	if err != nil {
		return "", err
	}
	return encryptPwd, nil
}

// Login 系统用户登录服务类
func (s *SysUserService) Login(req *model.SysUsersServiceSiginReq) (*model.SysUsers, error) {
	sysUserData, err := dao.SysUsers.FindOne("email=?", req.UserName)
	if err != nil {
		return nil, err
	}
	//判断用户信息是否为空
	if sysUserData == nil {
		return nil, errors.New("账号或密码错误")
	}
	//加密用户数密码，用来匹配是否一致
	passwordInput, err := s.GetUserPassword(req.Password)
	if err != nil {
		return nil, err
	}
	//密码错误
	if sysUserData.Password != passwordInput {
		return nil, errors.New("账号或密码错误")
	}
	return sysUserData, nil
}

// TokenCreate 创建用户token
func (s *SysUserService) TokenCreate(sysUserData *model.SysUsers, tokenDefine interface{}) (interface{}, error) {
	if sysUserData == nil {
		return nil, errors.New("用户信息不存在")
	}
	var token interface{}
	if tokenDefine != nil {
		token = tokenDefine
	} else {
		tokenString := "sys_user:" + gconv.String(sysUserData.Id)
		md5String, err := gmd5.EncryptString(tokenString)
		if err != nil {
			return nil, err
		}
		token = md5String
	}
	//配置缓存
	cache := Cache.New()
	cacheKey := "sys_user:" + gconv.String(token)
	//缓存服务
	if err := cache.Set(cacheKey, sysUserData, 2*time.Hour); err != nil {
		return nil, err
	}
	_, err := cache.Get(cacheKey)
	if err != nil {
		return nil, err
	}
	return token, nil
}

// AuthorizationGetUserData 通过分析请求中的head值获取当前请求用户数据
func (s *SysUserService) AuthorizationGetUserData(r *ghttp.Request) (*model.SysUsersServiceRes, error) {
	var authorizationArr []string
	//过滤分析用户token值
	authorization := r.Header.Get("Authorization")
	if authorization != "" {
		authorizationArr = gstr.Explode(" ", authorization)
	}
	if len(authorizationArr) < 2 {
		return nil, errors.New("授权凭证不存在")
	}
	userToken := authorizationArr[1]
	userData, err := SysUser.TokenGetData(userToken)
	if err != nil {
		return nil, err
	}
	if userData == nil {
		return nil, errors.New("用户不存在")
	}
	return userData, nil
}

// TokenGetData 通过token获取用户数据
func (s *SysUserService) TokenGetData(token string) (*model.SysUsersServiceRes, error) {
	//缓存服务
	cache := Cache.New()
	cacheKey := "sys_user:" + gconv.String(token)
	userDataJsonStr, err := cache.Get(cacheKey)
	if err != nil {
		return nil, err
	}
	if userDataJsonStr == nil {
		return nil, errors.New("用户登录信息已过期")
	}
	userDataJson, err := gjson.DecodeToJson(userDataJsonStr)
	if err != nil {
		return nil, err
	}
	userDataMapStruct := new(model.SysUsersServiceRes)
	if err := userDataJson.Struct(userDataMapStruct); err != nil {
		return nil, err
	}
	if userDataMapStruct.RoleIds != "" {
		//转换用户角色列表
		userRoleIdsJson, err := gjson.DecodeToJson(userDataMapStruct.RoleIds)
		if err != nil {
			panic(err)
		}
		userDataMapStruct.RoleIdsArr = userRoleIdsJson.Array()
		//将角色数据恢复到用户结构体中
		/*for _, v := range userRoleIdsJson.Array() {
			userRoleStruct := new(model.AntTreeSelectValue)
			err := gconv.Struct(v, &userRoleStruct)
			if err != nil {
				panic(err)
			}
			userDataMapStruct.RoleIdsArr = append(userDataMapStruct.RoleIdsArr, userRoleStruct)
		}*/
	}
	return userDataMapStruct, nil
}

// TokenDelete 删除清除token缓存
func (s *SysUserService) TokenDelete(token string) (interface{}, error) {
	//缓存服务
	cache := Cache.New()
	cacheKey := "sys_user:" + gconv.String(token)
	result, err := cache.Remove(cacheKey)
	if err != nil {
		return nil, err
	}
	return result, nil
}

// GetAdminUserConf 获取用户后台管理配置信息
func (s *SysUserService) GetAdminUserConf(userData *model.SysUsersServiceRes) (*garray.Array, *garray.Array, error) {
	//用户角色列表
	userRoleList, err := SysRole.GetRoleListByUserId(userData.Id)
	if err != nil {
		return nil, nil, err
	}
	var (
		userRoleNameList = garray.New() //用户角色名称列表
		userRoleIdList   []uint         //用户角色ID列表
		userPermNameList = garray.New() //用户权限名称列表
	)

	//收集用户权限名称列表和权限ID列表
	for _, roles := range userRoleList {
		userRoleNameList.Append(roles.Name)
		userRoleIdList = append(userRoleIdList, roles.RoleId)
	}
	//所有权限列表
	allPermissionList, err := SysPermission.GetAll()
	if err != nil {
		return nil, nil, err
	}
	//权限名称列表
	if userRoleNameList.Contains("super-admin") { //超级管理员
		for _, permissions := range allPermissionList {
			userPermNameList.Append(permissions.Name)
		}
	} else { //非超管
		userPermIds, err := SysPermission.GetPermissionIdsByRoleIds(userRoleIdList)
		if err != nil {
			return nil, nil, err
		}
		for _, permissions := range allPermissionList {
			if gconv.Bool(permissions.IsPublic) == true || userPermIds.Contains(gconv.Int(permissions.PermId)) {
				userPermNameList.Append(permissions.Name)
			}
		}
	}
	return userRoleNameList, userPermNameList, nil
}

// 获取用户分页列表
func (s *SysUserService) GetPageList(searchParams *model.SysUserGetListReq) (model.SysUserGetListRes, error) {
	var result model.SysUserGetListRes
	modelObj := dao.SysUsers.Safe()
	if searchParams.Name != "" {
		modelObj = modelObj.WhereLike(dao.SysUsers.Columns.Name, "%"+searchParams.Name+"%")
	}
	if searchParams.Email != "" {
		modelObj = modelObj.WhereLike(dao.SysUsers.Columns.Email, "%"+searchParams.Email+"%")
	}
	modelObj = modelObj.Unscoped()
	//查询总数
	total, err := modelObj.Count()
	if err != nil {
		return result, err
	}
	result.Total = total
	var userList []*model.SysUsersServiceRes
	//查询分页列表
	err = modelObj.Page(searchParams.Page, searchParams.PageSize).Scan(&userList)
	if err != nil {
		return result, err
	}
	//转换用户角色json数据
	for _, res := range userList {
		_ = json.Unmarshal([]byte(res.RoleIds), &res.RoleIdsArr)
		res.Password = ""
	}
	result.Data = userList
	return result, nil
}

// 保存用户数据
func (s *SysUserService) SaveUser(userData *model.SysUserSaveReq) error {
	return dao.SysUsers.DB.Transaction(func(tx *gdb.TX) error {
		//如设置密码则存储加密密码
		if userData.Password != "" {
			encryptPwd, err := s.GetUserPassword(userData.Password)
			if err != nil {
				return err
			}
			userData.Password = encryptPwd
		}
		//更新用户表
		rs, err := dao.SysUsers.TX(tx).Data(userData).OmitEmpty().Save()
		if err != nil {
			return err
		}
		userId, err := rs.LastInsertId()
		if err != nil {
			return err
		}
		//更新用户角色关联表
		var roleUserList []model.SysRoleUsers
		if len(userData.RoleIdsArr) > 0 {
			for _, roleIdVal := range userData.RoleIdsArr {
				roleUserList = append(roleUserList, model.SysRoleUsers{
					RoleId: gconv.Uint(roleIdVal.Value),
					UserId: gconv.Uint(userId),
				})
			}
			//删除旧的用户角色关系数据
			_, err := dao.SysRoleUsers.TX(tx).Unscoped().Where(dao.SysRoleUsers.Columns.UserId, userId).Delete()
			if err != nil {
				return err
			}
			//批量添加关联数据
			_, err = dao.SysRoleUsers.TX(tx).Save(roleUserList)
			if err != nil {
				return err
			}
		}
		return nil
	})
}

//禁用用户
func (s *SysUserService) DisableUser(userIds []uint) error {
	return dao.SysUsers.DB.Transaction(func(tx *gdb.TX) error {
		//删除用户数据
		_, err := dao.SysUsers.TX(tx).WhereIn(dao.SysUsers.Columns.Id, userIds).Delete()
		if err != nil {
			return err
		}
		//删除用户关联角色数据
		return nil
	})
}

//激活用户
func (s *SysUserService) EnableUser(userIds []uint) error {
	return dao.SysUsers.DB.Transaction(func(tx *gdb.TX) error {
		//恢复用户
		_, err := dao.SysUsers.TX(tx).Unscoped().WhereIn(dao.SysUsers.Columns.Id, userIds).Data(g.Map{"deleted_at": nil, "updated_at": gtime.Now().String()}).Update()
		if err != nil {
			return err
		}
		return nil
	})
}
